Add remaining files
[juce-lv2.git] / juce / source / extras / the jucer / src / properties / jucer_PositionPropertyBase.h
blob3d51a8b62e4f6f25f7a947d805363aa675ace04a
1 /*
2 ==============================================================================
4 This file is part of the JUCE library - "Jules' Utility Class Extensions"
5 Copyright 2004-11 by Raw Material Software Ltd.
7 ------------------------------------------------------------------------------
9 JUCE can be redistributed and/or modified under the terms of the GNU General
10 Public License (Version 2), as published by the Free Software Foundation.
11 A copy of the license is included in the JUCE distribution, or can be found
12 online at www.gnu.org/licenses.
14 JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
15 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
16 A PARTICULAR PURPOSE. See the GNU General Public License for more details.
18 ------------------------------------------------------------------------------
20 To release a closed-source product which uses JUCE, commercial licenses are
21 available: visit www.rawmaterialsoftware.com/juce for more information.
23 ==============================================================================
26 #ifndef __JUCER_POSITIONPROPERTYBASE_JUCEHEADER__
27 #define __JUCER_POSITIONPROPERTYBASE_JUCEHEADER__
29 #include "../ui/jucer_PaintRoutineEditor.h"
30 #include "../ui/jucer_ComponentLayoutEditor.h"
32 //==============================================================================
33 /**
34 Base class for a property that edits the x, y, w, or h of a PositionedRectangle.
36 class PositionPropertyBase : public PropertyComponent,
37 protected ChangeListener,
38 private ButtonListener
40 public:
41 enum ComponentPositionDimension
43 componentX = 0,
44 componentY = 1,
45 componentWidth = 2,
46 componentHeight = 3
49 PositionPropertyBase (Component* component_,
50 const String& name,
51 ComponentPositionDimension dimension_,
52 const bool includeAnchorOptions_,
53 const bool allowRelativeOptions_,
54 ComponentLayout* layout_)
55 : PropertyComponent (name),
56 layout (layout_),
57 component (component_),
58 dimension (dimension_),
59 includeAnchorOptions (includeAnchorOptions_),
60 allowRelativeOptions (allowRelativeOptions_)
62 addAndMakeVisible (button = new TextButton ("mode"));
63 button->addListener (this);
64 button->setTriggeredOnMouseDown (true);
65 button->setConnectedEdges (TextButton::ConnectedOnLeft | TextButton::ConnectedOnRight);
67 addAndMakeVisible (textEditor = new PositionPropLabel (*this));
70 ~PositionPropertyBase()
72 deleteAllChildren();
75 const String getText() const
77 RelativePositionedRectangle rpr (getPosition());
78 PositionedRectangle& p = rpr.rect;
79 String s;
81 switch (dimension)
83 case componentX:
84 if (p.getPositionModeX() == PositionedRectangle::proportionOfParentSize)
85 s << valueToString (p.getX() * 100.0) << '%';
86 else
87 s << valueToString (p.getX());
88 break;
90 case componentY:
91 if (p.getPositionModeY() == PositionedRectangle::proportionOfParentSize)
92 s << valueToString (p.getY() * 100.0) << '%';
93 else
94 s << valueToString (p.getY());
95 break;
97 case componentWidth:
98 if (p.getWidthMode() == PositionedRectangle::proportionalSize)
99 s << valueToString (p.getWidth() * 100.0) << '%';
100 else
101 s << valueToString (p.getWidth());
102 break;
104 case componentHeight:
105 if (p.getHeightMode() == PositionedRectangle::proportionalSize)
106 s << valueToString (p.getHeight() * 100.0) << '%';
107 else
108 s << valueToString (p.getHeight());
109 break;
111 default:
112 jassertfalse;
113 break;
116 return s;
119 static const String valueToString (const double n)
121 return String (roundToInt (n * 1000.0) / 1000.0);
124 void setText (const String& newText)
126 RelativePositionedRectangle rpr (getPosition());
127 PositionedRectangle p (rpr.rect);
128 const double value = newText.getDoubleValue();
130 switch (dimension)
132 case componentX:
133 if (p.getPositionModeX() == PositionedRectangle::proportionOfParentSize)
134 p.setX (value / 100.0);
135 else
136 p.setX (value);
137 break;
139 case componentY:
140 if (p.getPositionModeY() == PositionedRectangle::proportionOfParentSize)
141 p.setY (value / 100.0);
142 else
143 p.setY (value);
144 break;
146 case componentWidth:
147 if (p.getWidthMode() == PositionedRectangle::proportionalSize)
148 p.setWidth (value / 100.0);
149 else
150 p.setWidth (value);
151 break;
153 case componentHeight:
154 if (p.getHeightMode() == PositionedRectangle::proportionalSize)
155 p.setHeight (value / 100.0);
156 else
157 p.setHeight (value);
158 break;
160 default:
161 jassertfalse;
162 break;
165 if (p != rpr.rect)
167 rpr.rect = p;
168 setPosition (rpr);
172 void changeListenerCallback (ChangeBroadcaster*)
174 refresh();
177 void showMenu (ComponentLayout* layout)
179 RelativePositionedRectangle rpr (getPosition());
180 PositionedRectangle p (rpr.rect);
182 PositionedRectangle::AnchorPoint xAnchor = p.getAnchorPointX();
183 PositionedRectangle::AnchorPoint yAnchor = p.getAnchorPointY();
184 PositionedRectangle::PositionMode xMode = p.getPositionModeX();
185 PositionedRectangle::PositionMode yMode = p.getPositionModeY();
186 PositionedRectangle::SizeMode sizeW = p.getWidthMode();
187 PositionedRectangle::SizeMode sizeH = p.getHeightMode();
189 String relCompName ("parent");
191 Component* const relComp = layout != 0 ? layout->getComponentRelativePosTarget (component, (int) dimension) : 0;
193 if (relComp != 0)
194 relCompName = layout->getComponentMemberVariableName (relComp);
196 jassert (relCompName.isNotEmpty());
198 PopupMenu m;
200 if (dimension == componentX || dimension == componentY)
202 const PositionedRectangle::PositionMode posMode = (dimension == componentX) ? xMode : yMode;
204 m.addItem (10, ((dimension == componentX) ? "Absolute distance from left of "
205 : "Absolute distance from top of ") + relCompName,
206 true, posMode == PositionedRectangle::absoluteFromParentTopLeft);
208 m.addItem (11, ((dimension == componentX) ? "Absolute distance from right of "
209 : "Absolute distance from bottom of ") + relCompName,
210 true, posMode == PositionedRectangle::absoluteFromParentBottomRight);
212 m.addItem (12, "Absolute distance from centre of " + relCompName,
213 true, posMode == PositionedRectangle::absoluteFromParentCentre);
215 m.addItem (13, ((dimension == componentX) ? "Percentage of width of "
216 : "Percentage of height of ") + relCompName,
217 true, posMode == PositionedRectangle::proportionOfParentSize);
219 m.addSeparator();
221 if (includeAnchorOptions)
223 const PositionedRectangle::AnchorPoint anchor = (dimension == componentX) ? xAnchor : yAnchor;
225 m.addItem (14, (dimension == componentX) ? "Anchored at left of component"
226 : "Anchored at top of component",
227 true, anchor == PositionedRectangle::anchorAtLeftOrTop);
229 m.addItem (15, "Anchored at centre of component", true, anchor == PositionedRectangle::anchorAtCentre);
231 m.addItem (16, (dimension == componentX) ? "Anchored at right of component"
232 : "Anchored at bottom of component",
233 true, anchor == PositionedRectangle::anchorAtRightOrBottom);
236 else
238 const PositionedRectangle::SizeMode sizeMode = (dimension == componentWidth) ? sizeW : sizeH;
240 m.addItem (20, (dimension == componentWidth) ? "Absolute width"
241 : "Absolute height",
242 true, sizeMode == PositionedRectangle::absoluteSize);
244 m.addItem (21, ((dimension == componentWidth) ? "Percentage of width of "
245 : "Percentage of height of ") + relCompName,
246 true, sizeMode == PositionedRectangle::proportionalSize);
248 m.addItem (22, ((dimension == componentWidth) ? "Subtracted from width of "
249 : "Subtracted from height of ") + relCompName,
250 true, sizeMode == PositionedRectangle::parentSizeMinusAbsolute);
254 if (allowRelativeOptions && layout != 0)
256 m.addSeparator();
257 m.addSubMenu ("Relative to", layout->getRelativeTargetMenu (component, (int) dimension));
260 const int menuResult = m.showAt (button);
261 switch (menuResult)
263 case 10:
264 if (dimension == componentX)
265 xMode = PositionedRectangle::absoluteFromParentTopLeft;
266 else
267 yMode = PositionedRectangle::absoluteFromParentTopLeft;
268 break;
270 case 11:
271 if (dimension == componentX)
272 xMode = PositionedRectangle::absoluteFromParentBottomRight;
273 else
274 yMode = PositionedRectangle::absoluteFromParentBottomRight;
275 break;
277 case 12:
278 if (dimension == componentX)
279 xMode = PositionedRectangle::absoluteFromParentCentre;
280 else
281 yMode = PositionedRectangle::absoluteFromParentCentre;
282 break;
284 case 13:
285 if (dimension == componentX)
286 xMode = PositionedRectangle::proportionOfParentSize;
287 else
288 yMode = PositionedRectangle::proportionOfParentSize;
289 break;
291 case 14:
292 if (dimension == componentX)
293 xAnchor = PositionedRectangle::anchorAtLeftOrTop;
294 else
295 yAnchor = PositionedRectangle::anchorAtLeftOrTop;
296 break;
298 case 15:
299 if (dimension == componentX)
300 xAnchor = PositionedRectangle::anchorAtCentre;
301 else
302 yAnchor = PositionedRectangle::anchorAtCentre;
303 break;
305 case 16:
306 if (dimension == componentX)
307 xAnchor = PositionedRectangle::anchorAtRightOrBottom;
308 else
309 yAnchor = PositionedRectangle::anchorAtRightOrBottom;
310 break;
312 case 20:
313 if (dimension == componentWidth)
314 sizeW = PositionedRectangle::absoluteSize;
315 else
316 sizeH = PositionedRectangle::absoluteSize;
318 break;
320 case 21:
321 if (dimension == componentWidth)
322 sizeW = PositionedRectangle::proportionalSize;
323 else
324 sizeH = PositionedRectangle::proportionalSize;
326 break;
328 case 22:
329 if (dimension == componentWidth)
330 sizeW = PositionedRectangle::parentSizeMinusAbsolute;
331 else
332 sizeH = PositionedRectangle::parentSizeMinusAbsolute;
334 break;
336 default:
337 if (allowRelativeOptions && layout != 0)
338 layout->processRelativeTargetMenuResult (component, (int) dimension, menuResult);
340 break;
343 Rectangle<int> parentArea;
345 if (component->findParentComponentOfClass ((ComponentLayoutEditor*) 0) != 0)
347 parentArea.setSize (component->getParentWidth(), component->getParentHeight());
349 else if (dynamic_cast <PaintRoutineEditor*> (component->getParentComponent()) != 0)
351 parentArea = dynamic_cast <PaintRoutineEditor*> (component->getParentComponent())->getComponentArea();
353 else
355 jassertfalse
358 int x, xw, y, yh, w, h;
359 rpr.getRelativeTargetBounds (parentArea, layout, x, xw, y, yh, w, h);
361 PositionedRectangle xyRect (p);
362 PositionedRectangle whRect (p);
364 xyRect.setModes (xAnchor, xMode, yAnchor, yMode, sizeW, sizeH,
365 Rectangle<int> (x, y, xw, yh));
367 whRect.setModes (xAnchor, xMode, yAnchor, yMode, sizeW, sizeH,
368 Rectangle<int> (x, y, w, h));
370 p.setModes (xAnchor, xMode, yAnchor, yMode, sizeW, sizeH,
371 Rectangle<int> (x, y, xw, yh));
373 p.setX (xyRect.getX());
374 p.setY (xyRect.getY());
375 p.setWidth (whRect.getWidth());
376 p.setHeight (whRect.getHeight());
378 if (p != rpr.rect)
380 rpr.rect = p;
381 setPosition (rpr);
385 void resized()
387 const Rectangle<int> r (getLookAndFeel().getPropertyComponentContentPosition (*this));
389 button->changeWidthToFitText (r.getHeight());
390 button->setTopRightPosition (r.getRight(), r.getY());
392 textEditor->setBounds (r.getX(), r.getY(), button->getX() - r.getX(), r.getHeight());
395 void refresh()
397 textEditor->setText (getText(), false);
400 void buttonClicked (Button*)
402 showMenu (layout);
403 refresh(); // (to clear the text editor if it's got focus)
406 void textWasEdited()
408 const String newText (textEditor->getText());
409 if (getText() != newText)
410 setText (newText);
413 //==============================================================================
414 virtual void setPosition (const RelativePositionedRectangle& newPos) = 0;
416 virtual const RelativePositionedRectangle getPosition() const = 0;
418 protected:
419 class PositionPropLabel : public Label
421 PositionPropertyBase& owner;
422 int maxChars;
423 bool isMultiline;
425 public:
426 PositionPropLabel (PositionPropertyBase& owner_)
427 : Label (String::empty, String::empty),
428 owner (owner_)
430 setEditable (true, true, false);
432 setColour (backgroundColourId, Colours::white);
433 setColour (textColourId, Colours::black);
434 setColour (outlineColourId, findColour (ComboBox::outlineColourId));
436 setColour (TextEditor::textColourId, Colours::black);
437 setColour (TextEditor::backgroundColourId, Colours::white);
438 setColour (TextEditor::outlineColourId, findColour (ComboBox::outlineColourId));
441 ~PositionPropLabel()
445 TextEditor* createEditorComponent()
447 TextEditor* textEditor = Label::createEditorComponent();
448 textEditor->setInputRestrictions (14, "0123456789.-%");
450 return textEditor;
453 void textWasEdited()
455 owner.textWasEdited();
459 ComponentLayout* layout;
460 PositionPropLabel* textEditor;
461 TextButton* button;
463 Component* component;
464 ComponentPositionDimension dimension;
465 const bool includeAnchorOptions, allowRelativeOptions;
469 #endif // __JUCER_POSITIONPROPERTYBASE_JUCEHEADER__